/*
 * Fichier: ExpressionsRegulieres.java
 * Crée le: 1 février 2010.
 * Modifié: 4 mars 2012.
 * Auteurs: Sébastien ESTIENNE.
 * SiteWeb: http://www.prog-info.org/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package chapitre9;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * <p>Classe illustrant le fonctionnement des expressions rationnelles ou régulières.</p>
 * @author Sébastien ESTIENNE.
 */
public class ExpressionsRegulieres extends JFrame
{
   /** Zone de texte pour les résultats. */
   private JTextArea zoneSortie;
   
   /**
    * <p>Serial version UID.</p>
    */
   private static final long serialVersionUID = 1L;
   
   /**
    * <p>Construction de l'application.</p>
    */
   public ExpressionsRegulieres()
   {
      // Appel du constructeur de la classe JFrame.
      super("Expressions régulières");

      // Ajoute les composants au conteneur.
      this.zoneSortie = new JTextArea();
      getContentPane().add(new JScrollPane(this.zoneSortie), BorderLayout.CENTER);

      // Vérifie qu'une chaîne est alphanumérique.
      verifierAlphaNum("Exemple1");
      verifierAlphaNum("Premier_Exemple");
      this.zoneSortie.append("\n");
      
      // Vérifie le format d'une date (jj/mm/aaaa).
      verifierDate("03/01/10");
      verifierDate("32/01/2010");
      verifierDate("08/01/2010");
      this.zoneSortie.append("\n");
      
      // Vérifie la validité d'une adresse email.
      verifierEmail("sebastien");
      verifierEmail("sebastien@domaine");
      verifierEmail("sebastien@domaine.com");
      this.zoneSortie.append("\n");
      
      // Vérifie q'une phrase commence par le mot "Le".
      verifierDebut("Un texte.", "Le");
      verifierDebut("Le texte.", "Le");
      this.zoneSortie.append("\n");
      
      // Vérifie qu'une phrase finit par un ".".
      verifierFin("Vive les expressions régulières!", ".");
      verifierFin("Les expressions régulières c'est puissant.", ".");
      this.zoneSortie.append("\n");
      
      // Vérifie qu'une chaîne ne contient pas de caractère blanc.
      verifierSansEspace("Cette phrase est facile à lire.");
      verifierSansEspace("Cettephraseestdifficileàlire.");
      this.zoneSortie.append("\n");
      
      // Compte le nombre de mots.
      compterMots("Un carré est un rectangle.");
      this.zoneSortie.append("\n");
      
      // Extrait les mots commençant par un "a".
      extraireMots("Ils s'aiment comme chien et chat", "c");
      this.zoneSortie.append("\n");
      
      // Découpe une chaîne de caractères en mots.
      //decouperChaine("");this.zoneSortie.append("\n"); split
      
      // Remplace un mot par un autre dans une phrase.
      //remplacerMot("");this.zoneSortie.append("\n"); replace

      // Modifie les propriétés de la fenêtre.
      setSize(600, 200);
      setLocation(100, 100);
      setVisible(true);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères passée est alphanumérique.</p>
    * @param chaine La chaîne de caractères à évaluer.
    */
   public void verifierAlphaNum(String chaine)
   {
      Pattern alphaNum = Pattern.compile("^[A-Za-z0-9]+$"); // ou "^\\w+$"
      Matcher resultat = alphaNum.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' est une chaîne alphanumérique.\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' n'est pas une chaîne alphanumérique.\n");
      }
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères passée est au format de date jj/mm/aaaa.</p>
    * @param chaine La chaîne de caractères à évaluer.
    */
   public void verifierDate(String chaine)
   {
      // Cette expression vérifie seulement que le jour est entre 1 et 31, le mois entre 1 et 12 
      // et que l'année est sur 4 chiffre. Elle ne prend pas en compte le nombre de jours qui 
      // diffère d'un mois à un autre ni les années bissextile.
      Pattern date = Pattern.compile("^(0[1-9]|[1-2][0-9]|3[0-1])/(0[1-9]|1[0-2])/[0-9]{4}$");
      Matcher resultat = date.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' est une date au format (jj/mm/aaaa).\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' n'est pas une date au format (jj/mm/aaaa).\n");
      }
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères passée est une adresse email vallide.</p>
    * @param chaine La chaîne de caractères à évaluer.
    */
   public void verifierEmail(String chaine)
   {
      Pattern email = Pattern.compile("^[A-Za-z0-9\\._-]+@[A-Za-z0-9\\.-]+\\.[A-Za-z]{2,4}$");
      Matcher resultat = email.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' est une adresse email valide.\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' n'est pas une adresse email valide.\n");
      }
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères passée commence par la chaîne recherchée.</p>
    * @param chaine La chaîne de caractères à évaluer.
    * @param recherche La chaîne de caractère à chercher en début.
    */
   public void verifierDebut(String chaine, String recherche)
   {
      Pattern debut = Pattern.compile("^\\Q" + recherche + "\\E.*$");
      Matcher resultat = debut.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' commence par '" + recherche + "'.\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' ne commence pas par '" + recherche + "'.\n");
      }
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères passée fini par la chaîne recherchée.</p>
    * @param chaine La chaîne de caractères à évaluer.
    * @param recherche La chaîne de caractère à chercher en fin.
    */
   public void verifierFin(String chaine, String recherche)
   {
      Pattern fin = Pattern.compile("^.*\\Q" + recherche + "\\E$");
      Matcher resultat = fin.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' fini par '" + recherche + "'.\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' ne fini pas par '" + recherche + "'.\n");
      }
   }
   
   /**
    * <p>Vérifie que la chaîne de caractères ne contient pas d'espace.</p>
    * @param chaine La chaîne de caractères à évaluer.
    */
   public void verifierSansEspace(String chaine)
   {
      Pattern fin = Pattern.compile("^[^\\ ]*$");
      Matcher resultat = fin.matcher(chaine);
      if(resultat.find())
      {
         this.zoneSortie.append("'" + chaine + "' ne contient pas d'espace.\n");
      }
      else
      {
         this.zoneSortie.append("'" + chaine + "' contient des espaces.\n");
      }
   }
   
   /**
    * <p>Compte le nombre de mots dans la chaîne de caractère passée.</p>
    * @param chaine La chaîne de caractère à évaluer.
    */
   public void compterMots(String chaine)
   {
      Pattern fin = Pattern.compile("([^\\s\\.!:/;?,]+)");
      Matcher resultat = fin.matcher(chaine);
      int cpt = 0;
      while(resultat.find())
      {
         cpt++;
      }
      this.zoneSortie.append("'" + chaine + "' contient " + cpt + " mot(s).\n");
   }
   
   /**
    * <p>Extrait les mots commençant par le chaine passée en paramètre.</p>
    * @param chaine La chaîne de caractère à évaluer.
    * @param begin L'expression recherchée en début de mot.
    */
   public void extraireMots(String chaine, String begin)
   {
      Pattern fin = Pattern.compile("(\\Q" + begin + "\\E[^\\s]*)");
      Matcher resultat = fin.matcher(chaine);
      int cpt = 0;
      List<String> mots = new ArrayList<String>();
      while(resultat.find())
      {
         cpt++;
         mots.add(resultat.group());
      }
      this.zoneSortie.append("'" + chaine + "' contient " + cpt + " mot(s) commençant par '" 
          + begin + "' : ");
      int i = 0;
      for(String mot : mots)
      {
         this.zoneSortie.append(mot);
         if(i != mots.size() - 1)
         {
            this.zoneSortie.append(", ");
         }
         else
         {
            this.zoneSortie.append(".\n");
         }
         i++;
      }
   }
   
   /**
    * <p>Débute l'exécution du programme.</p>
    * @param args Les paramètres de la ligne de commande.
    */
   public static void main(String[] args)
   {
      new ExpressionsRegulieres();
   }
}
